package com.example.yian.controller;

import cn.afterturn.easypoi.word.WordExportUtil;
import com.alibaba.fastjson.TypeReference;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectRequest;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.yian.config.OssConfig;
import com.example.yian.entity.*;
import com.example.yian.service.*;
import com.example.yian.util.FileUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.Instant;
import java.util.*;

@RestController
public class SecurityRiskExportController {

    @Autowired
    private SecurityRiskService riskService;

    @Autowired
    private ProjectInfoService projectInfoService;

    @Autowired
    private OssConfig ossConfig;

    @Autowired
    private FileUtil fileUtil;

    @Autowired
    private SecurityRiskReportService reportService;

    @Autowired
    private WeChatAuthService weChatAuthService;

    @Autowired
    private TextSearchService textSearchService;
    @GetMapping("/TestaddRiskReport")
    public  Map<String, Object> addReport1(HttpServletResponse Response, @RequestBody String strRiskIds) throws IOException {
        Map<String, Object> response = new HashMap<>();
        List<SecurityRisk> riskList = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();

        ProjectInfo curInfo = new ProjectInfo();
        List<String> textResponseList = new ArrayList<>();

        // 使用 split 方法按逗号分割字符串
        String[] stringItems = strRiskIds.split(",");

        // 将字符串数组转换为 Long 数组
        Long[] riskIds = new Long[0];
        try {
            riskIds = Arrays.stream(stringItems)
                    .map(Long::parseLong)
                    .toArray(Long[]::new);
        } catch (NumberFormatException e) {
            System.err.println("Invalid number format in the input string.");
            response.put("code", 200);
            response.put("msg", "解析riskIds失败");
            response.put("data", "");
            return response;
        }

        // 假设riskIds数组至少有一个元素
        for (Long riskId : riskIds) {
            Optional<SecurityRisk> risk = riskService.getSecurityRiskWithDetails(riskId);

            if (risk.isEmpty()) {
                response.put("code", 200);
                response.put("msg", "隐患不存在");
                response.put("data", "");
                 return response;
            }

            Long userId = risk.get().GetUserId();

            if (userId == null) {
                response.put("code", 200);
                response.put("msg", "用户不存在");
                response.put("data", "");
                return response;
            }
            Optional<ProjectInfo> projectInfo = projectInfoService.getProjectInfoByUserId(userId);
            if (projectInfo.isEmpty()) {
                response.put("code", 200);
                response.put("msg", "项目信息不存在");
                response.put("data", "");
                return response;
            }
            curInfo = projectInfo.get();

            Optional<SecurityRisk> detail = riskService.getSecurityRiskWithDetails(riskId);

            Optional<TextSearchResponse> textResponse = textSearchService.findByTextId(detail.get().getTextId());

            if (textResponse.isEmpty()) {
                response.put("code", 200);
                response.put("msg", "文本信息不存在");
                response.put("data", "");
                return response;
            }

            textResponseList.add(textResponse.get().getContent());
            riskList.add(risk.get());
        }


        map.put("project_name", curInfo.getProjectName());
        map.put("contruction_unit", curInfo.getConstructionUnit());
        map.put("design_unit", curInfo.getDesignUnit());
        map.put("supervision_unit", curInfo.getSupervisionUnit());
        map.put("inspection_team_name", curInfo.getInspectionTeamName());
        map.put("inspection_personnel", curInfo.getInspectionPersonnel());
        map.put("riskList",textResponseList);

        SecurityRiskReport riskReport = new SecurityRiskReport();

        //代替
        OSS ossClient = null;
        String url = null;
        String reportId = null;
        try {
            // 1.获取模板文件路径 - 重点）
         /*   String templatePath = filePath("Templates/Template.docx").getAbsolutePath();

            // 打印出模板文件的完整路径 - 校验路径是否存在
            File templateFile = new File(templatePath);
            if (templateFile.exists()) {
                System.out.println("模板文件存在: " + templateFile.getAbsolutePath());
            } else {
                System.out.println("模板文件不存在: " + templateFile.getAbsolutePath());
            }

            // 打印出模板文件的完整路径 - 校验路径是否存在
            if (templateFile.exists()) {
                System.out.println("模板文件存在: " + templateFile.getAbsolutePath());
            } else {
                System.out.println("模板文件不存在: " + templateFile.getAbsolutePath());
                response.put("code", 200);
                response.put("msg", "模板文件不存在");
                response.put("data", "");
                return response;
            }
            // 2.映射模板，替换数据
            XWPFDocument word = WordExportUtil.exportWord07(templatePath, map);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            word.write(byteArrayOutputStream);*/

            // 使用 ClassPathResource 获取文件
          /*  ClassPathResource resource = new ClassPathResource("Templates/Template.docx");
            File templateFile = resource.getFile();*/
          //  File templateFile = ResourceUtils.getFile("classpath:Templates/Template.docx");
           /* ClassPathResource resource = new ClassPathResource("Templates/Template.docx");
            File templateFile = resource.getFile();

            // 打印出模板文件的完整路径 - 校验路径是否存在
            if (templateFile.exists()) {
                System.out.println("模板文件存在: " + resource.getURI().getPath());
            } else {
                System.out.println("模板文件不存在: " + resource.getURI().getPath());
                response.put("code", 200);
                response.put("msg", "模板文件不存在");
                response.put("data", "");
                return response;
            }*/
            ClassPathResource resource = new ClassPathResource("Templates/Template.docx");

           /* String templatePath = resource.getURI().getPath();

            if(templatePath.isEmpty())
            {
                System.out.println("resource.getURI().getPath() is empty");
            }
            File templateFile = new File(templatePath);
            if (templateFile.exists()) {
                System.out.println("模板文件存在: " + templateFile.getAbsolutePath());
            } else {
                System.out.println("模板文件不存在: " + templateFile.getAbsolutePath());
            }*/

            // 从 InputStream 创建临时文件
            File tempFile = File.createTempFile("temp", ".docx");
            try (InputStream inputStream = resource.getInputStream(); // 获取 InputStream
                 FileOutputStream fos = new FileOutputStream(tempFile)) {
                byte[] buffer = new byte[1024];
                int length;
                while ((length = inputStream.read(buffer)) > 0) {
                    fos.write(buffer, 0, length);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            // 使用临时文件路径调用 WordExportUtil.exportWord07
            try {
                String templatePath = tempFile.getAbsolutePath();
                XWPFDocument word = WordExportUtil.exportWord07(tempFile.getAbsolutePath(), map);
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                word.write(byteArrayOutputStream);

                // 4. 上传到OSS
                reportId = UUID.randomUUID().toString();
                String fileName = reportId + ".docx"; // 添加扩展名
                ossClient = new OSSClientBuilder().build(
                        ossConfig.getEndpoint(),
                        ossConfig.getAccessKeyId(),
                        ossConfig.getAccessKeySecret()
                );

                // 将字节数组转换为输入流
                InputStream fileInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());

                // 上传文件到OSS
                ossClient.putObject(new PutObjectRequest(ossConfig.getBucketName(), fileName, fileInputStream));

                // 获取文件URL
                url = "https://" + ossConfig.getBucketName() + "." + ossConfig.getEndpoint() + "/" + fileName;


                reportService.addReport(url, curInfo.getUserId(), reportId);

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 删除临时文件
                Files.deleteIfExists(Paths.get(tempFile.getAbsolutePath()));
            }
            // 2.映射模板，替换数据
           /* XWPFDocument word = WordExportUtil.exportWord07(resource.getURI().getPath()/*templateFile.getAbsolutePath(), map);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            word.write(byteArrayOutputStream);*/

            // 4. 上传到OSS
          /*  reportId = UUID.randomUUID().toString();
            String fileName = reportId + ".docx"; // 添加扩展名
            ossClient = new OSSClientBuilder().build(
                    ossConfig.getEndpoint(),
                    ossConfig.getAccessKeyId(),
                    ossConfig.getAccessKeySecret()
            );

            // 将字节数组转换为输入流
            InputStream fileInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());

            // 上传文件到OSS
            ossClient.putObject(new PutObjectRequest(ossConfig.getBucketName(), fileName, fileInputStream));

            // 获取文件URL
            url = "https://" + ossConfig.getBucketName() + "." + ossConfig.getEndpoint() + "/" + fileName;


            reportService.addReport(url, curInfo.getUserId(), reportId);

            // 3.设置返回参数的字符集
            Response.reset();
            Response.setHeader("Access-Control-Allow-Origin", "*");
            Response.setContentType("application/msexcel");
            Response.setContentType("text/html; charset=UTF-8");
            // 4.设置响应类型为Word文档
            Response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
            // 5.中文文件名处理，否则报错
            String encodedFileName = URLEncoder.encode("简介", "UTF-8");
            Response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName + ".docx");*/


            // 6.将Word文档发送到浏览器
            //word.write(Response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ossClient.shutdown();
        }

        response.put("code", 200);
        response.put("msg", "成功");
        Map<String, Object> responseData = new HashMap<>();
        responseData.put("url", url);
        responseData.put("ReportId", reportId);
        response.put("data", responseData);
        return response;
    }

    @PostMapping("/addRiskReport")
    public  Map<String, Object> addReport(HttpServletResponse Response, @RequestBody String strRiskIds) throws IOException {
        Map<String, Object> response = new HashMap<>();
        List<SecurityRisk> riskList = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        ProjectInfo curInfo = new ProjectInfo();
        List<String> textResponseList = new ArrayList<>();
        ObjectMapper mapper = new ObjectMapper();
        String strRiskId = new String();
        try {
            // 将 JSON 字符串转换为 JsonNode
            JsonNode jsonNode = mapper.readTree(strRiskIds);

            // 提取 strRiskIds 字段的值
            strRiskId = jsonNode.get("riskIds").asText();

        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        String[] stringItems = strRiskId.split(",");

        // 将字符串数组转换为 Long 数组
        Long[] riskIds = new Long[0];
        try {
            riskIds = Arrays.stream(stringItems)
                    .map(Long::parseLong)
                    .toArray(Long[]::new);
        } catch (NumberFormatException e) {
            System.err.println("Invalid number format in the input string.");
            response.put("code", 200);
            response.put("msg", "解析riskIds失败");
            response.put("data", "");
            return response;
        }

        // 假设riskIds数组至少有一个元素
        for (Long riskId : riskIds) {
            Optional<SecurityRisk> risk = riskService.getSecurityRiskWithDetails(riskId);

            if (risk.isEmpty()) {
                response.put("code", 200);
                response.put("msg", "隐患不存在");
                response.put("data", "");
                return response;
            }

            Long userId = risk.get().GetUserId();

            if (userId == null) {
                response.put("code", 200);
                response.put("msg", "用户不存在");
                response.put("data", "");
                return response;
            }
            Optional<ProjectInfo> projectInfo = projectInfoService.getProjectInfoByUserId(userId);
            if (projectInfo.isEmpty()) {
                response.put("code", 200);
                response.put("msg", "项目信息不存在");
                response.put("data", "");
                return response;
            }
            curInfo = projectInfo.get();

            Optional<SecurityRisk> detail = riskService.getSecurityRiskWithDetails(riskId);

            Optional<TextSearchResponse> textResponse = textSearchService.findByTextId(detail.get().getTextId());

            if (textResponse.isEmpty()) {
                response.put("code", 200);
                response.put("msg", "文本信息不存在");
                response.put("data", "");
                return response;
            }

            textResponseList.add(textResponse.get().getContent());
            riskList.add(risk.get());
        }


        map.put("project_name", curInfo.getProjectName());
        map.put("contruction_unit", curInfo.getConstructionUnit());
        map.put("design_unit", curInfo.getDesignUnit());
        map.put("supervision_unit", curInfo.getSupervisionUnit());
        map.put("inspection_team_name", curInfo.getInspectionTeamName());
        map.put("inspection_personnel", curInfo.getInspectionPersonnel());
        map.put("riskList",textResponseList);

        SecurityRiskReport riskReport = new SecurityRiskReport();

        //代替
        OSS ossClient = null;
        String url = null;
        String reportId = null;
        try {
            // 1.获取模板文件路径
            ClassPathResource resource = new ClassPathResource("Templates/Template.docx");
            // 从 InputStream 创建临时文件
            File tempFile = File.createTempFile("temp", ".docx");
            try (InputStream inputStream = resource.getInputStream(); // 获取 InputStream
                 FileOutputStream fos = new FileOutputStream(tempFile)) {
                byte[] buffer = new byte[1024];
                int length;
                while ((length = inputStream.read(buffer)) > 0) {
                    fos.write(buffer, 0, length);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            // 使用临时文件路径调用 WordExportUtil.exportWord07
            try {
                String templatePath = tempFile.getAbsolutePath();
                XWPFDocument word = WordExportUtil.exportWord07(tempFile.getAbsolutePath(), map);
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                word.write(byteArrayOutputStream);

                // 4. 上传到OSS
                reportId = UUID.randomUUID().toString();
                String fileName = reportId + ".docx"; // 添加扩展名
                ossClient = new OSSClientBuilder().build(
                        ossConfig.getEndpoint(),
                        ossConfig.getAccessKeyId(),
                        ossConfig.getAccessKeySecret()
                );

                // 将字节数组转换为输入流
                InputStream fileInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());

                // 上传文件到OSS
                ossClient.putObject(new PutObjectRequest(ossConfig.getBucketName(), fileName, fileInputStream));

                // 获取文件URL
                url = "https://" + ossConfig.getBucketName() + "." + ossConfig.getEndpoint() + "/" + fileName;


                reportService.addReport(url, curInfo.getUserId(), reportId);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 删除临时文件
                Files.deleteIfExists(Paths.get(tempFile.getAbsolutePath()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ossClient.shutdown();
        }

        response.put("code", 200);
        response.put("msg", "成功");
        Map<String, Object> responseData = new HashMap<>();
        responseData.put("url", url);
        responseData.put("ReportId", reportId);
        response.put("data", responseData);
        return response;
    }

    @PostMapping("/getHisReport")
    public Map<String, Object> getReportList(
            @RequestBody Map<String, Object> requestParams,
            @RequestHeader("Authorization") String token) {
        Map<String, Object> response = new LinkedHashMap<>();
        Optional<Long> userIdOpt = weChatAuthService.getUserIdFromToken(token);

        if (!userIdOpt.isPresent()) {
            response.put("code", 401);
            response.put("msg", "未授权");
            response.put("time", Instant.now().toEpochMilli());
            response.put("data", new HashMap<>());
            return response;
        }
        Long userId = userIdOpt.get();
        // 从请求体中提取分页参数
        Integer pageNum = (Integer) requestParams.getOrDefault("page", 1);
        Integer pageSize = (Integer) requestParams.getOrDefault("size", 1000);
        String  startTime = (String) requestParams.getOrDefault("startTime", "2024-08-03");
        String endTime = (String) requestParams.getOrDefault("endTime", "2099-08-19");

        Page<SecurityRisk> page = new Page<>(pageNum, pageSize);
        IPage<SecurityRiskReport> riskPage = reportService.getRiskReportListsByUserId(userId, pageNum, pageSize, startTime,endTime);
        response.put("code", 200);
        response.put("msg", "成功");
        response.put("time", Instant.now().toEpochMilli());
        response.put("total", riskPage.getTotal());

        //重新拿取一把
        List<SecurityRiskReport> riskReports = riskPage.getRecords();
        List<Map<String, Object>> dataWithExtraFields = new ArrayList<>();
        for (SecurityRiskReport riskReport : riskReports) {
            Map<String, Object> dataItem = new HashMap<>();
            dataItem.put("userId",riskReport.getUserId());
            dataItem.put("ReportId", riskReport.getReportId()); // 假设 otherField 是另一个 Long 类型的字段
            dataItem.put("url",riskReport.getOos_url());
            dataItem.put("createdAt", riskReport.getCreatedAt());
            dataItem.put("updatedAt", riskReport.getUpdatedAt());
            dataWithExtraFields.add(dataItem);
        }
        response.put("data",dataWithExtraFields);
        return response;
    }


    /**
     * 从OSS下载Word文档并返回给客户端
     * @param reportId 报告ID，用于确定文件名
     * @param response HttpServletResponse对象
     * @throws IOException 如果发生IO异常
     */
    @GetMapping("/downloadRiskReport/{reportId}")
    public void downloadWordDocument(@PathVariable String reportId, HttpServletResponse response) throws IOException {
        OSS ossClient = null;
        try {
            ossClient = new OSSClientBuilder().build(
                    ossConfig.getEndpoint(),
                    ossConfig.getAccessKeyId(),
                    ossConfig.getAccessKeySecret()
            );

            // 构建文件名
            String fileName = reportId + ".docx";

            // 创建 GetObjectRequest
            GetObjectRequest getObjectRequest = new GetObjectRequest(ossConfig.getBucketName(), fileName);

            // 从 OSS 下载文件
            OSSObject ossObject = ossClient.getObject(getObjectRequest);

            // 检查 ossObject 是否为 null
            if (ossObject == null) {
                throw new RuntimeException("Failed to get the object from OSS.");
            }

            InputStream inputStream = ossObject.getObjectContent();

            response.reset();
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setContentType("application/msexcel");
            response.setContentType("text/html; charset=UTF-8");
            // 4.设置响应类型为Word文档
            response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
            // 5.中文文件名处理，否则报错
            String encodedFileName = URLEncoder.encode("简介", "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + reportId + ".docx");

            // 将文件内容写入到 HTTP 响应输出流
            OutputStream outputStream = response.getOutputStream();
            IOUtils.copy(inputStream, outputStream);
            outputStream.flush();
        } catch (OSSException e) {
            // OSS 服务端异常
            System.err.println("OSS service exception: " + e.getMessage());
        } catch (ClientException e) {
            // 客户端异常
            System.err.println("Client exception: " + e.getMessage());
        } catch (IOException e) {
            // 输入输出异常
            System.err.println("IO exception: " + e.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    public File filePath(String modelFileName) {
        // 获取类加载器
        ClassLoader classLoader = FileUtil.class.getClassLoader();
        // 尝试从类路径中加载资源
        URL resource = classLoader.getResource(modelFileName);
        return new File(resource.getFile());
    }
}